/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.ufrn.engcomp.pds.helloopc.visao;

import br.ufrn.engcomp.pds.helloopc.controle.ICadastroController;
import br.ufrn.engcomp.pds.helloopc.modelo.dominio.IEntidade;
import java.lang.reflect.ParameterizedType;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author Felipe Rivas
 */
public abstract class CadastroBase<T extends IEntidade> extends JanelaBase {
    protected T entidade;
    protected Operacao operacaoAtual;

    protected abstract ICadastroController getController();
    protected abstract JDialog getJanelaEdicao();
    protected abstract JTable getTabela();
    protected abstract void setTextoBotaoOK(String texto);

    protected abstract void limparJanelaEdicao();
    protected abstract void preencherJanelaEdicao();
    protected abstract void preencherTabela();
    protected abstract void preencherEntidade();
    protected abstract void adicionarBotoesTabela();
    protected abstract String getDescricaoEntidade();
    protected abstract Object[] getLinhaDados(T entidade);

    protected void processarAcaoBotaoInserir() {
        operacaoAtual = Operacao.INSERIR;

        executarJanelaEdicao();
    }
    protected void processarAcaoBotaoOK() {
        try {
            if (operacaoAtual == Operacao.INSERIR) {
                entidade = (T)Class.forName(getClasse().getName()).newInstance();

                preencherEntidade();

                getController().inserir(entidade);
            } else if (operacaoAtual == Operacao.ATUALIZAR) {
                preencherEntidade();

                getController().atualizar(entidade);
            }

            getJanelaEdicao().setVisible(false);

            atualizarTabela(entidade);
        } catch (Exception ex) {
            //mostrarErro("Não foi possível inserir/atualizar registro da tabela.");
        }
    }
    protected void processarAcaoBotaoCancelar() {
        entidade = null;

        operacaoAtual = Operacao.INSERIR;

        getJanelaEdicao().setVisible(false);
    }
    protected void atualizar() {
        Object id = getTabela().getValueAt(getTabela().getSelectedRow(), 0);

        entidade = (T)getController().buscarPorId(id);

        operacaoAtual = Operacao.ATUALIZAR;

        executarJanelaEdicao();
    }
    protected void remover() {
        try {
            operacaoAtual = Operacao.REMOVER;

            if (Confirmar("Tem certeza que deseja excluir este registro?") == JOptionPane.OK_OPTION) {
                Object id = getTabela().getValueAt(getTabela().getSelectedRow(), 0);

                getController().remover(id);

                atualizarTabela(null);
            }
        } catch (Exception ex) {
            //mostrarErro("Não foi possível remover registro da tabela.");
        }
    }
    protected void executarJanelaEdicao() {
        limparJanelaEdicao();

        if (operacaoAtual == Operacao.INSERIR) {
            getJanelaEdicao().setTitle("Inserir " + getDescricaoEntidade());
            setTextoBotaoOK("Inserir");
        } else if (operacaoAtual == Operacao.ATUALIZAR) {
            getJanelaEdicao().setTitle("Atualizar " + getDescricaoEntidade());
            setTextoBotaoOK("Atualizar");

            preencherJanelaEdicao();
        }

        getJanelaEdicao().pack();
        getJanelaEdicao().setLocationRelativeTo(this);
        getJanelaEdicao().setVisible(true);
    }
    protected void atualizarTabela(T entidade) throws Exception {
        atualizarTabela(entidade, operacaoAtual);
    }
    protected void atualizarTabela(T entidade, Operacao operacao) throws Exception {
        switch (operacao) {
            case INSERIR: {
                    ((DefaultTableModel)getTabela().getModel()).addRow(this.getLinhaDados(entidade));

                    ((DefaultTableModel)getTabela().getModel()).fireTableRowsInserted(getTabela().getRowCount(), getTabela().getRowCount());
                }
                break;
            case ATUALIZAR: {
                    int linhaSelecionada = getTabela().getSelectedRow();

                    ((DefaultTableModel)getTabela().getModel()).removeRow(linhaSelecionada);
                    ((DefaultTableModel)getTabela().getModel()).insertRow(linhaSelecionada, this.getLinhaDados(entidade));

                    ((DefaultTableModel)getTabela().getModel()).fireTableRowsUpdated(linhaSelecionada, linhaSelecionada);
                }
                break;
            case REMOVER: {
                    int linhaSelecionada = getTabela().getSelectedRow();

                    ((DefaultTableModel)getTabela().getModel()).removeRow(linhaSelecionada);

                    ((DefaultTableModel)getTabela().getModel()).fireTableRowsDeleted(linhaSelecionada, linhaSelecionada);
                }
                break;
            default:
                throw new Exception("Tipo de operação inválida.");
        }
    }
    protected final Class<T> getClasse() {
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }
}
